# class Person(object):
#     pass
# p = Person()
# print(id(p))   # 打印内存地址 10进制
# print(hex(id(p)))  # 打印内存地址 16进制
# print(p)

# # pyhon 会缓存 常用数据类型的对象地址  就是创建num1 和 num2的地址相同
# num1 = 2
# num2 = 2
# print(hex(id(num1)), hex(id(num2)))


# -------------------1.引用计数器------------------
# # 查看引用计数器 sys  模块会自动+1 正常结果是要减1的
# import sys
# class Person(object):
#     pass
# p1 = Person()  # 引用计数器 = 1
# print(sys.getrefcount(p1))
#
# p2 = p1      # 引用计数器 = 2
# print(sys.getrefcount(p1))
#
# del p1    # 引用计数器 = 1
#
# del p2    # 引用计数器 = 1



# -------------------2.循环引用问题------------------
# pythond的内存管理：引用计数器机制 + 垃圾回收机制（性能较低 解决循环引用）

# import objgraph
#
# class Person(object):
#     pass
#
# class Dog(object):
#     pass
#
# p = Person()
# d = Dog()
#
# print(objgraph.count('Person'))
# print(objgraph.count('Dog'))
#
# p.pet = d
# d.master = p
#
#
# del p
# del d
#
# print('删除之后的Person个数', objgraph.count('Person'))
# print('删除之后的Dog个数', objgraph.count('Dog'))


# -------------------3.垃圾回收机制--->找到循环引用，清除对象------------------
# 原理步骤：
# 1、收集所有的"容器对象"（列表、字典、元祖、自定义对象），通过双向链表（集合）进行引用
# 2、针对每一个"容器对象"，通过一个变量gc_refs来记录当前的引用计数器
# 3、对象每个'容器对象'，找到他引用的'容器对象'，并将这个'容器对象'的引用计数器 -1
# 4、经过步骤3之后，如果一个'容器对象'的引用计数器未0 就代表这个东西可以被回收啦，肯定是循环引用导致的


# 分代回收 ： 优化垃圾回收性能

#
# 垃圾回收器  新增的对象个数 - 消亡的对象 达到一定的阈值才会触发垃圾回收
# # 阈值设置
# import gc
#
# print(gc.get_threshold())
# # (700, 10, 10)  默认当阈值大于700 检测一次   大于10 1代检测   大于10 2代加测
#
# # 设置垃圾检测
# gc.set_threshold(1000, 5, 5)


# 垃圾回收机制触发时机自动回收：1.开启机制  2.设置阈值
# import gc
#
# # 判断是否开启垃圾回收
# isenable = gc.isenabled()
#
# if isenable == False:
#       # 开启回收
#     gc.enable()
#
# # 设置阈值
# gc.set_threshold(500, 10, 10)


# 垃圾回收机制触发时机手动回收- 解决循环引用 gc.collect(1)

# 解决循环引用方案 ：
# 1、weakref 弱引用 - 一个对象的弱引用  一对多的引用用需要弱引用字典
# 2、指向None
# 3. gc.collect(1)

import objgraph   # 引用计数器count
import gc         # 垃圾回收机制
import weakref    # 弱引用
class Person(object):
    def __del__(self):
        print('Person对象被释放啦')

class Dog(object):
    def __del__(self):
        print('Dog对象被释放啦')

p = Person()
d = Dog()
# 循环引用
p.pet = d
d.master = p
# d.master = weakref.ref(p)  #解决循环引用方式一 弱引用的应用
# p.pet = None     # 解决循环引用方式二 指向None
del p
del d
# 解决循环引用方式三 垃圾回收机制手动回收
# gc.collect(1)

print(objgraph.count('Person'))
print(objgraph.count('Dog'))















